home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / files.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  24KB  |  762 lines

  1. /*
  2.  * files.c: misc code to access files used by Moria 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <errno.h>
  13.  
  14. #ifndef MSDOS
  15. #include <sys/param.h>
  16. #endif
  17.  
  18. #include "constant.h"
  19. #include "config.h"
  20. #include "types.h"
  21. #include "externs.h"
  22.  
  23. #ifdef ibm032
  24. #include <ctype.h>
  25. #endif
  26.  
  27. #ifdef MSDOS
  28. extern int          errno;
  29.  
  30. #endif
  31.  
  32. #if defined(GEMDOS) && (__STDC__ == 0)
  33. #include <access.h>
  34. char               *strcat();
  35.  
  36. #endif
  37.  
  38. #ifdef USG
  39. #ifndef ATARIST_MWC
  40. #include <string.h>
  41. #include <fcntl.h>
  42. #ifdef __MINT__
  43. #include <ctype.h>
  44. #endif
  45. #endif
  46. #else
  47. #include <strings.h>
  48. #ifndef VMS
  49. #include <sys/file.h>
  50. #else
  51. #include <file.h>
  52. #endif
  53. #endif
  54.  
  55. #ifndef VMS
  56. #if defined(ultrix) || defined(USG)
  57. void exit();
  58.  
  59. #endif
  60. #endif
  61.  
  62.  
  63. /* This is done first in main.c, so I'll rudely drop it into the front
  64.  * of files.c...  If NEW_FILEPATHS is defined, we'll look for the ANGBAND_PATH
  65.  * environment variable, and then look for the files in there.  This is
  66.  * much nicer than having explicit paths, and should help us make things
  67.  * more portable.  Now, if only someone would graft on the NetHack display
  68.  * code...
  69.  *
  70.  * This is rather inelegant code; no checks are made for malloc() or
  71.  * realloc() failures.  If you malloc/realloc are broken, you're in
  72.  * trouble, and your compiler vendor needs a good swift kick in the
  73.  * forehead. [cjh]
  74.  */
  75. #ifdef NEW_FILEPATHS
  76. char *ANGBAND_TST;        /* was LIBDIR(test)            */
  77. char *ANGBAND_HOU;        /* was LIBDIR(files/hours)        */
  78. char *ANGBAND_MOR;        /* was LIBDIR(files/news)        */
  79. char *ANGBAND_TOP;        /* was LIBDIR(files/newscores)        */
  80. char *ANGBAND_BONES;        /* was LIBDIR(bones)            */
  81. char *ANGBAND_HELP;        /* was LIBDIR(files/roglcmds.hlp)    */
  82. char *ANGBAND_ORIG_HELP;    /* was LIBDIR(files/origcmds.hlp)    */
  83. char *ANGBAND_WIZ_HELP;        /* was LIBDIR(files/rwizcmds.hlp)    */
  84. char *ANGBAND_OWIZ_HELP;    /* was LIBDIR(files/owizcmds.hlp)    */
  85. char *ANGBAND_WELCOME;        /* was LIBDIR(files/welcome.hlp)    */
  86. char *ANGBAND_LOG;        /* was LIBDIR(files/ANGBAND.log)    */
  87. char *ANGBAND_VER;        /* was LIBDIR(files/version.hlp)    */
  88. char *ANGBAND_LOAD;        /* was LIBDIR(files/loadcheck)        */
  89. char *ANGBAND_WIZ;        /* was LIBDIR(files/wizards)        */
  90. char *ANGBAND_SAV;        /* was LIBDIR(save)            */
  91.  
  92. void get_file_paths()
  93. {
  94. #ifndef MAXPATHLEN
  95. #define BOZO_MAXPATHLEN
  96. #define MAXPATHLEN 512
  97. #endif
  98.  
  99.     char *angband_path;
  100.  
  101. /* Find the path to our files...  if the ANGBAND_PATH environment var
  102.  * isn't set, use DEFAULT_PATH to look for the files.  If your system
  103.  * can't do environment variables, you'll have to kludge this.  [cjh]
  104.  */
  105.  
  106.     angband_path = getenv( "ANGBAND_PATH" );
  107.     if (angband_path == NULL) {
  108.  
  109. #if 0 /* I don't think this is appropriate, particularly since this may
  110.        * well be set by a system-wide games administrator.  -CWS */
  111.  
  112.        fprintf(stderr, "Warning: ANGBAND_PATH not set!\n" );
  113.        fprintf(stderr, "Warning: Using %s for ANGBAND_PATH.\n", DEFAULT_PATH );
  114. #endif
  115.     angband_path = (char *)malloc( strlen( DEFAULT_PATH ) + 1 );
  116.     strcpy( angband_path, DEFAULT_PATH );
  117.     }
  118.  
  119.     ANGBAND_TST = (char *)malloc( MAXPATHLEN );
  120.     strcpy( ANGBAND_TST, angband_path );
  121.     strcat( ANGBAND_TST, PATH_SEP );
  122.     strcat( ANGBAND_TST, "test" );
  123.     ANGBAND_TST = (char *)realloc( ANGBAND_TST, strlen( ANGBAND_TST ) + 1 );
  124.  
  125.     ANGBAND_HOU = (char *)malloc( MAXPATHLEN );
  126.     strcpy( ANGBAND_HOU, angband_path );
  127.     strcat( ANGBAND_HOU, PATH_SEP );
  128.     strcat( ANGBAND_HOU, "files" );
  129.     strcat( ANGBAND_HOU, PATH_SEP );
  130.     strcat( ANGBAND_HOU, "hours" );
  131.     ANGBAND_HOU = (char *)realloc( ANGBAND_HOU, strlen( ANGBAND_HOU ) + 1 );
  132.  
  133.     ANGBAND_MOR = (char *)malloc( MAXPATHLEN );
  134.     strcpy( ANGBAND_MOR, angband_path );
  135.     strcat( ANGBAND_MOR, PATH_SEP );
  136.     strcat( ANGBAND_MOR, "files" );
  137.     strcat( ANGBAND_MOR, PATH_SEP );
  138.     strcat( ANGBAND_MOR, "news" );
  139.     ANGBAND_MOR = (char *)realloc( ANGBAND_MOR, strlen( ANGBAND_MOR ) + 1 );
  140.  
  141.     ANGBAND_TOP = (char *)malloc( MAXPATHLEN );
  142.     strcpy( ANGBAND_TOP, angband_path );
  143.     strcat( ANGBAND_TOP, PATH_SEP );
  144.     strcat( ANGBAND_TOP, "files" );
  145.     strcat( ANGBAND_TOP, PATH_SEP );
  146.     strcat( ANGBAND_TOP, "newscores" );
  147.     ANGBAND_TOP = (char *)realloc( ANGBAND_TOP, strlen( ANGBAND_TOP ) + 1 );
  148.  
  149.     ANGBAND_BONES = (char *)malloc( MAXPATHLEN );
  150.     strcpy( ANGBAND_BONES, angband_path );
  151.     strcat( ANGBAND_BONES, PATH_SEP );
  152.     strcat( ANGBAND_BONES, "bones" );
  153.     ANGBAND_BONES = (char *)realloc( ANGBAND_BONES, strlen( ANGBAND_BONES ) + 1 );
  154.  
  155.     ANGBAND_HELP = (char *)malloc( MAXPATHLEN );
  156.     strcpy( ANGBAND_HELP, angband_path );
  157.     strcat( ANGBAND_HELP, PATH_SEP );
  158.     strcat( ANGBAND_HELP, "files" );
  159.     strcat( ANGBAND_HELP, PATH_SEP );
  160.     strcat( ANGBAND_HELP, "roglcmds.hlp" );
  161.     ANGBAND_HELP = (char *)realloc( ANGBAND_HELP, strlen( ANGBAND_HELP ) + 1 );
  162.  
  163.     ANGBAND_ORIG_HELP = (char *)malloc( MAXPATHLEN );
  164.     strcpy( ANGBAND_ORIG_HELP, angband_path );
  165.     strcat( ANGBAND_ORIG_HELP, PATH_SEP );
  166.     strcat( ANGBAND_ORIG_HELP, "files" );
  167.     strcat( ANGBAND_ORIG_HELP, PATH_SEP );
  168.     strcat( ANGBAND_ORIG_HELP, "origcmds.hlp" );
  169.     ANGBAND_ORIG_HELP = (char *)realloc(ANGBAND_ORIG_HELP,
  170.                     strlen( ANGBAND_ORIG_HELP ) + 1 );
  171.  
  172.     ANGBAND_WIZ_HELP = (char *)malloc( MAXPATHLEN );
  173.     strcpy( ANGBAND_WIZ_HELP, angband_path );
  174.     strcat( ANGBAND_WIZ_HELP, PATH_SEP );
  175.     strcat( ANGBAND_WIZ_HELP, "files" );
  176.     strcat( ANGBAND_WIZ_HELP, PATH_SEP );
  177.     strcat( ANGBAND_WIZ_HELP, "rwizcmds.hlp" );
  178.     ANGBAND_WIZ_HELP = (char *)realloc(ANGBAND_WIZ_HELP,
  179.                        strlen( ANGBAND_WIZ_HELP ) + 1 );
  180.  
  181.     ANGBAND_OWIZ_HELP = (char *)malloc( MAXPATHLEN );
  182.     strcpy( ANGBAND_OWIZ_HELP, angband_path );
  183.     strcat( ANGBAND_OWIZ_HELP, PATH_SEP );
  184.     strcat( ANGBAND_OWIZ_HELP, "files" );
  185.     strcat( ANGBAND_OWIZ_HELP, PATH_SEP );
  186.     strcat( ANGBAND_OWIZ_HELP, "owizcmds.hlp" );
  187.     ANGBAND_OWIZ_HELP = (char *)realloc(ANGBAND_OWIZ_HELP,
  188.                     strlen( ANGBAND_OWIZ_HELP ) + 1 );
  189.  
  190.     ANGBAND_WELCOME = (char *)malloc( MAXPATHLEN );
  191.     strcpy( ANGBAND_WELCOME, angband_path );
  192.     strcat( ANGBAND_WELCOME, PATH_SEP );
  193.     strcat( ANGBAND_WELCOME, "files" );
  194.     strcat( ANGBAND_WELCOME, PATH_SEP );
  195.     strcat( ANGBAND_WELCOME, "welcome.hlp" );
  196.     ANGBAND_WELCOME = (char *)realloc( ANGBAND_WELCOME, strlen( ANGBAND_WELCOME ) + 1 );
  197.  
  198.     ANGBAND_LOG = (char *)malloc( MAXPATHLEN );
  199.     strcpy( ANGBAND_LOG, angband_path );
  200.     strcat( ANGBAND_LOG, PATH_SEP );
  201.     strcat( ANGBAND_LOG, "files" );
  202.     strcat( ANGBAND_LOG, PATH_SEP );
  203.     strcat( ANGBAND_LOG, "ANGBAND.log" );
  204.     ANGBAND_LOG = (char *)realloc( ANGBAND_LOG, strlen( ANGBAND_LOG ) + 1 );
  205.  
  206.     ANGBAND_VER = (char *)malloc( MAXPATHLEN );
  207.     strcpy( ANGBAND_VER, angband_path );
  208.     strcat( ANGBAND_VER, PATH_SEP );
  209.     strcat( ANGBAND_VER, "files" );
  210.     strcat( ANGBAND_VER, PATH_SEP );
  211.     strcat( ANGBAND_VER, "version.hlp" );
  212.     ANGBAND_VER = (char *)realloc( ANGBAND_VER, strlen( ANGBAND_VER ) + 1 );
  213.  
  214.     ANGBAND_LOAD = (char *)malloc( MAXPATHLEN );
  215.     strcpy( ANGBAND_LOAD, angband_path );
  216.     strcat( ANGBAND_LOAD, PATH_SEP );
  217.     strcat( ANGBAND_LOAD, "files" );
  218.     strcat( ANGBAND_LOAD, PATH_SEP );
  219.     strcat( ANGBAND_LOAD, "loadcheck" );
  220.     ANGBAND_LOAD = (char *)realloc( ANGBAND_LOAD, strlen( ANGBAND_LOAD ) + 1 );
  221.  
  222.     ANGBAND_WIZ = (char *)malloc( MAXPATHLEN );
  223.     strcpy( ANGBAND_WIZ, angband_path );
  224.     strcat( ANGBAND_WIZ, PATH_SEP );
  225.     strcat( ANGBAND_WIZ, "files" );
  226.     strcat( ANGBAND_WIZ, PATH_SEP );
  227.     strcat( ANGBAND_WIZ, "wizards" );
  228.     ANGBAND_WIZ = (char *)realloc( ANGBAND_WIZ, strlen( ANGBAND_WIZ ) + 1 );
  229.  
  230.     ANGBAND_SAV = (char *)malloc( MAXPATHLEN );
  231.     strcpy( ANGBAND_SAV, angband_path );
  232.     strcat( ANGBAND_SAV, PATH_SEP );
  233.     strcat( ANGBAND_SAV, "save" );
  234.     ANGBAND_SAV = (char *)realloc( ANGBAND_SAV, strlen( ANGBAND_SAV ) + 1 );
  235.  
  236.     return;
  237. }
  238.  
  239. #ifdef BOZO_MAXPATHLEN
  240. #undef BOZO_MAXPATHLEN
  241. #undef MAXPATHLEN
  242. #endif /* BOZO_MAXPATHLEN */
  243.  
  244. #endif /* NEW_FILEPATHS */
  245.  
  246.  
  247. /* Not touched for Mac port */
  248. /*
  249.  * init_scorefile Open the score file while we still have the setuid
  250.  * privileges.  Later when the score is being written out, you must be sure
  251.  * to flock the file so we don't have multiple people trying to write to it
  252.  * at the same time. Craig Norborg (doc)        Mon Aug 10 16:41:59
  253.  * EST 1987 
  254.  */
  255. void 
  256. init_scorefile()
  257. {
  258. #ifdef SET_UID
  259.     if (1 > (highscore_fd = my_topen(ANGBAND_TOP, O_RDWR | O_CREAT, 0644)))
  260. #else
  261.     if (1 > (highscore_fd = my_topen(ANGBAND_TOP, O_RDWR | O_CREAT, 0666)))
  262. #endif
  263.     {
  264.     (void)fprintf(stderr, "Can't open score file \"%s\"\n", ANGBAND_TOP);
  265.     exit(1);
  266.     }
  267. }
  268.  
  269.  
  270. /* Attempt to open the intro file            -RAK-     */
  271. /* This routine also checks the hours file vs. what time it is    -Doc */
  272. void 
  273. read_times()
  274. {
  275.     register int i;
  276.     vtype        in_line;
  277.     FILE        *file1;
  278.  
  279. #ifdef CHECKHOURS
  280. /* Attempt to read hours.dat.     If it does not exist,       */
  281. /* inform the user so he can tell the wizard about it     */
  282.     if ((file1 = my_tfopen(ANGBAND_HOU, "r")) != NULL) {
  283.     while (fgets(in_line, 80, file1) != NULL)
  284.         if (strlen(in_line) > 3) {
  285.         if (!strncmp(in_line, "SUN:", 4))
  286.             (void)strcpy(days[0], in_line);
  287.         else if (!strncmp(in_line, "MON:", 4))
  288.             (void)strcpy(days[1], in_line);
  289.         else if (!strncmp(in_line, "TUE:", 4))
  290.             (void)strcpy(days[2], in_line);
  291.         else if (!strncmp(in_line, "WED:", 4))
  292.             (void)strcpy(days[3], in_line);
  293.         else if (!strncmp(in_line, "THU:", 4))
  294.             (void)strcpy(days[4], in_line);
  295.         else if (!strncmp(in_line, "FRI:", 4))
  296.             (void)strcpy(days[5], in_line);
  297.         else if (!strncmp(in_line, "SAT:", 4))
  298.             (void)strcpy(days[6], in_line);
  299.         }
  300.     (void)fclose(file1);
  301.     } else {
  302.     restore_term();
  303.     (void)fprintf(stderr, "There is no hours file \"%s\".\nPlease inform the wizard, %s, so he can correct this!\n", ANGBAND_HOU, WIZARD);
  304.     exit(1);
  305.     }
  306.  
  307. /* Check the hours, if closed    then exit. */
  308.     if (!check_time()) {
  309.     if ((file1 = my_tfopen(ANGBAND_HOU, "r")) != NULL) {
  310.         clear_screen();
  311.         for (i = 0; fgets(in_line, 80, file1) != NULL; i++)
  312.         put_buffer(in_line, i, 0);
  313.         (void)fclose(file1);
  314.         pause_line(23);
  315.     }
  316.     exit_game();
  317.     }
  318. #endif                   /* CHECK_HOURS */
  319.  
  320. /* Print the introduction message, news, etc.         */
  321.     if ((file1 = my_tfopen(ANGBAND_MOR, "r")) != NULL) {
  322.     clear_screen();
  323.     for (i = 0; fgets(in_line, 80, file1) != NULL; i++)
  324.         put_buffer(in_line, i, 0);
  325.     pause_line(23);
  326.     (void)fclose(file1);
  327.     }
  328. }
  329.  
  330. /*
  331.  * File perusal.        -CJS- primitive, but portable 
  332.  */
  333. void 
  334. helpfile(filename)
  335. const char *filename;
  336. {
  337.     bigvtype tmp_str;
  338.     FILE    *file;
  339.     char     input;
  340.     int      i;
  341.  
  342.     file = my_tfopen(filename, "r");
  343.     if (file == NULL) {
  344.     (void)sprintf(tmp_str, "Can not find help file \"%s\".\n", filename);
  345.     prt(tmp_str, 0, 0);
  346.     return;
  347.     }
  348.     save_screen();
  349.  
  350.     while (!feof(file)) {
  351.     clear_screen();
  352.     for (i = 0; i < 23; i++)
  353.         if (fgets(tmp_str, BIGVTYPESIZ - 1, file) != NULL)
  354.         put_buffer(tmp_str, i, 0);
  355.     prt("[Press any key to continue.]", 23, 23);
  356.     input = inkey();
  357.     if (input == ESCAPE)
  358.         break;
  359.     }
  360.  
  361.     (void)fclose(file);
  362.     restore_screen();
  363. }
  364.  
  365. /* Prints a list of random objects to a file.  Note that -RAK-     */
  366. /* the objects produced is a sampling of objects which         */
  367. /* be expected to appear on that level.                 */
  368. void 
  369. print_objects()
  370. {
  371.     register int         i;
  372.     int                  nobj, j, level;
  373.     vtype                filename1;
  374.     bigvtype             tmp_str;
  375.     register FILE       *file1;
  376.     register inven_type *i_ptr;
  377.  
  378.     prt("Produce objects on what level?: ", 0, 0);
  379.     level = 0;
  380.     if (!get_string(tmp_str, 0, 32, 10))
  381.     return;
  382.     level = atoi(tmp_str);
  383.     prt("Produce how many objects?: ", 0, 0);
  384.     nobj = 0;
  385.     if (!get_string(tmp_str, 0, 27, 10))
  386.     return;
  387.     nobj = atoi(tmp_str);
  388.     if ((nobj > 0) && (level > -1) && (level < 1201)) {
  389.     if (nobj > 10000)
  390.         nobj = 10000;
  391.     prt("File name: ", 0, 0);
  392.     if (get_string(filename1, 0, 11, 64)) {
  393.         if (strlen(filename1) == 0)
  394.         return;
  395.         if ((file1 = my_tfopen(filename1, "w")) != NULL) {
  396.         (void)sprintf(tmp_str, "%d", nobj);
  397.         prt(strcat(tmp_str, " random objects being produced..."), 0, 0);
  398.         put_qio();
  399.         (void)fprintf(file1, "*** Random Object Sampling:\n");
  400.         (void)fprintf(file1, "*** %d objects\n", nobj);
  401.         (void)fprintf(file1, "*** For Level %d\n", level);
  402.         (void)fprintf(file1, "\n");
  403.         (void)fprintf(file1, "\n");
  404.         j = popt();
  405.         for (i = 0; i < nobj; i++) {
  406.             if (randint(MAX_DUNGEON_OBJ) == 1) {
  407.             int                 tmp;
  408.  
  409.         again:
  410.             tmp = randint(MAX_OBJECTS - (SPECIAL_OBJ - 1)) +
  411.                 (SPECIAL_OBJ - 1) - 1;
  412.             switch (tmp) {
  413.               case (SPECIAL_OBJ - 1):
  414.                 if (object_list[tmp].level <= level)
  415.                 msg_print("*Remove Curse*");
  416.                 break;
  417.               case (SPECIAL_OBJ):
  418.                 if (object_list[tmp].level <= level)
  419.                 msg_print("[Resistance of Scarabtarices]");
  420.                 break;
  421.               case (SPECIAL_OBJ + 1):
  422.                 if (object_list[tmp].level <= level)
  423.                 msg_print("[Mordenkainen's Escapes]");
  424.                 break;
  425.               case (SPECIAL_OBJ + 2):
  426.                 if (object_list[tmp].level <= level)
  427.                 msg_print("[Kelek's Grimoire of Power]");
  428.                 break;
  429.               case (SPECIAL_OBJ + 3):
  430.                 if (randint(2) == 1)
  431.                 goto again;
  432.                 if (object_list[tmp].level <= level)
  433.                 msg_print("[Tenser's Transformations]");
  434.                 break;
  435.               case (SPECIAL_OBJ + 4):
  436.                 if (randint(2) == 1)
  437.                 goto again;
  438.                 if (object_list[tmp].level <= level)
  439.                 msg_print("[Raal's Tome of Destruction]");
  440.                 break;
  441.               case (SPECIAL_OBJ + 5):
  442.                 if (object_list[tmp].level <= level)
  443.                 msg_print("[Ethereal Openings]");
  444.                 break;
  445.               case (SPECIAL_OBJ + 6):
  446.                 if (object_list[tmp].level <= level)
  447.                 msg_print("[Godly Insights]");
  448.                 break;
  449.               case (SPECIAL_OBJ + 7):
  450.                 if (object_list[tmp].level <= level)
  451.                 msg_print("[Purifications and Healing]");
  452.                 break;
  453.               case (SPECIAL_OBJ + 8):
  454.                 if (object_list[tmp].level <= level)
  455.                 msg_print("[Wrath of God]");
  456.                 break;
  457.               case (SPECIAL_OBJ + 9):
  458.                 if (randint(2) > 1)
  459.                 goto again;
  460.                 if (object_list[tmp].level <= level)
  461.                 msg_print("[Holy Infusions]");
  462.                 break; /* End of Books */
  463.               case (SPECIAL_OBJ + 10):    /* Narya */
  464.                 if (randint(4) > 1)
  465.                 goto again;
  466.                 if (NARYA)
  467.                 goto again;
  468.                 if (object_list[tmp].level <= level)
  469.                 msg_print("Narya");
  470.                 NARYA = TRUE;
  471.                 break;
  472.               case (SPECIAL_OBJ + 11):    /* Nenya */
  473.                 if (randint(5) > 1)
  474.                 goto again;
  475.                 if (NENYA)
  476.                 goto again;
  477.                 if (object_list[tmp].level <= level)
  478.                 msg_print("Nenya");
  479.                 NENYA = TRUE;
  480.                 break;
  481.               case (SPECIAL_OBJ + 12):    /* Vilya */
  482.                 if (randint(6) > 1)
  483.                 goto again;
  484.                 if (VILYA)
  485.                 goto again;
  486.                 if (object_list[tmp].level <= level)
  487.                 msg_print("Vilya");
  488.                 VILYA = TRUE;
  489.                 break;
  490.               case (SPECIAL_OBJ + 13):    /* The Ring of Power */
  491.                 if (randint(10) > 1)
  492.                 goto again;
  493.                 if (POWER)
  494.                 goto again;
  495.                 if (object_list[tmp].level <= level)
  496.                 msg_print("Power (The One Ring)");
  497.                 POWER = TRUE;
  498.                 break;
  499.               case (SPECIAL_OBJ + 14):    /* Dragon Scale mails */
  500.               case (SPECIAL_OBJ + 15):
  501.               case (SPECIAL_OBJ + 16):
  502.               case (SPECIAL_OBJ + 17):
  503.               case (SPECIAL_OBJ + 18):
  504.               case (SPECIAL_OBJ + 19):
  505.               case (SPECIAL_OBJ + 20):
  506.                 if (randint(2) > 1)
  507.                 goto again;
  508.                 if (object_list[tmp].level <= level)
  509.                 msg_print("Dragon Scale Mail");
  510.                 break;
  511.               case (SPECIAL_OBJ + 23):    /* Multi-Hued Dragon
  512.                              * Scale Mail */
  513.                 if (randint(3) > 1)
  514.                 goto again;
  515.                 if (object_list[tmp].level <= level)
  516.                 msg_print("Multi-Hued Dragon Scale Mail");
  517.                 break;
  518.             }
  519.             if (object_list[tmp].level > level)
  520.                 continue;
  521.             invcopy(&t_list[j], tmp);
  522.             if (object_list[t_list[j].index].tval == TV_HARD_ARMOR)
  523.                 t_list[j].toac += 10 + randint(10);
  524.             i_ptr = &t_list[j];
  525.             store_bought(i_ptr);
  526.             objdes(tmp_str, i_ptr, TRUE);
  527.             } else {
  528.             invcopy(&t_list[j],
  529.                 sorted_objects[get_obj_num(level, FALSE)]);
  530.             magic_treasure(j, level, 0, FALSE);
  531.             i_ptr = &t_list[j];
  532.             store_bought(i_ptr);
  533.             if (i_ptr->flags & TR_CURSED)
  534.                 add_inscribe(i_ptr, ID_DAMD);
  535.             objdes(tmp_str, i_ptr, TRUE);
  536.             }
  537.             (void)fprintf(file1, "%d %s.\n", i_ptr->level, tmp_str);
  538.         }
  539.         pusht((int16) j);
  540.         (void)fclose(file1);
  541.         prt("Completed.", 0, 0);
  542.         } else
  543.         prt("File could not be opened.", 0, 0);
  544.     }
  545.     } else
  546.     prt("Parameters no good.", 0, 0);
  547. }
  548.  
  549.  
  550. /* Print the character to a file or device        -RAK-     */
  551. int 
  552. file_character(filename1)
  553. char *filename1;
  554. {
  555.     register int          i;
  556.     int                   j, xbth, xbthb, xfos, xsrh, xstl, xdis, xsave, xdev;
  557.     vtype                 xinfra;
  558.     int                   fd;
  559.     register FILE        *file1;
  560.     bigvtype              prt2;
  561.     register struct misc *p_ptr;
  562.     register inven_type  *i_ptr;
  563.     vtype                 out_val, prt1;
  564.     const char           *p, *colon, *blank;
  565.  
  566.     fd = my_topen(filename1, O_WRONLY | O_CREAT | O_EXCL, 0644);
  567.     if (fd < 0 && errno == EEXIST) {
  568.     (void)sprintf(out_val, "Replace existing file %s?", filename1);
  569.     if (get_Yn(out_val))
  570.         fd = my_topen(filename1, O_WRONLY, 0644);
  571.     }
  572.     if (fd >= 0) {
  573.     /*
  574.      * on some non-unix machines, fdopen() is not reliable, hence must call
  575.      * close() and then fopen() 
  576.      */
  577.     (void)close(fd);
  578.     file1 = my_tfopen(filename1, "w");
  579.     } else
  580.     file1 = NULL;
  581.  
  582.     if (file1 != NULL) {
  583.     prt("Writing character sheet...", 0, 0);
  584.     put_qio();
  585.     colon = ":";
  586.     blank = " ";
  587.     (void)fprintf(file1, "%c\n\n", CTRL('L'));
  588.     (void)fprintf(file1, " Name%9s %-23s", colon, py.misc.name);
  589.     (void)fprintf(file1, "Age%11s %6d ", colon, (int)py.misc.age);
  590.     cnv_stat(py.stats.use_stat[A_STR], prt1);
  591.     (void)fprintf(file1, "   STR : %s\n", prt1);
  592.     (void)fprintf(file1, " Race%9s %-23s", colon, race[py.misc.prace].trace);
  593.     (void)fprintf(file1, "Height%8s %6d ", colon, (int)py.misc.ht);
  594.     cnv_stat(py.stats.use_stat[A_INT], prt1);
  595.     (void)fprintf(file1, "   INT : %s\n", prt1);
  596.     (void)fprintf(file1, " Sex%10s %-23s", colon,
  597.               (py.misc.male ? "Male" : "Female"));
  598.     (void)fprintf(file1, "Weight%8s %6d ", colon, (int)py.misc.wt);
  599.     cnv_stat(py.stats.use_stat[A_WIS], prt1);
  600.     (void)fprintf(file1, "   WIS : %s\n", prt1);
  601.     (void)fprintf(file1, " Class%8s %-23s", colon,
  602.               class[py.misc.pclass].title);
  603.     (void)fprintf(file1, "Social Class : %6d ", py.misc.sc);
  604.     cnv_stat(py.stats.use_stat[A_DEX], prt1);
  605.     (void)fprintf(file1, "   DEX : %s\n", prt1);
  606.     (void)fprintf(file1, " Title%8s %-23s", colon, title_string());
  607.     (void)fprintf(file1, "%22s", blank);
  608.     cnv_stat(py.stats.use_stat[A_CON], prt1);
  609.     (void)fprintf(file1, "   CON : %s\n", prt1);
  610.     (void)fprintf(file1, "%34s", blank);
  611.     (void)fprintf(file1, "%26s", blank);
  612.     cnv_stat(py.stats.use_stat[A_CHR], prt1);
  613.     (void)fprintf(file1, "   CHR : %s\n\n", prt1);
  614.  
  615.     (void)fprintf(file1, " + To Hit    : %6d", py.misc.dis_th);
  616.     (void)fprintf(file1, "%7sLevel      :%9d", blank, (int)py.misc.lev);
  617.     (void)fprintf(file1, "   Max Hit Points : %6d\n", py.misc.mhp);
  618.     (void)fprintf(file1, " + To Damage : %6d", py.misc.dis_td);
  619.     (void)fprintf(file1, "%7sExperience :%9ld", blank, (long)py.misc.exp);
  620.     (void)fprintf(file1, "   Cur Hit Points : %6d\n", py.misc.chp);
  621.     (void)fprintf(file1, " + To AC     : %6d", py.misc.dis_tac);
  622.     (void)fprintf(file1, "%7sMax Exp    :%9ld", blank, (long)py.misc.max_exp);
  623.     (void)fprintf(file1, "   Max Mana%8s %6d\n", colon, py.misc.mana);
  624.     (void)fprintf(file1, "   Total AC  : %6d", py.misc.dis_ac);
  625.     if (py.misc.lev >= MAX_PLAYER_LEVEL)
  626.         (void)fprintf(file1, "%7sExp to Adv.:%9s", blank, "****");
  627.     else
  628.         (void)fprintf(file1, "%7sExp to Adv.:%9ld", blank,
  629.               (long) (player_exp[py.misc.lev - 1] *
  630.                    py.misc.expfact / 100));
  631.     (void)fprintf(file1, "   Cur Mana%8s %6d\n", colon, py.misc.cmana);
  632.     (void)fprintf(file1, "%28sGold%8s%9ld\n", blank, colon, (long)py.misc.au);
  633.  
  634.     p_ptr = &py.misc;
  635.     xbth = p_ptr->bth + p_ptr->ptohit * BTH_PLUS_ADJ
  636.         + (class_level_adj[p_ptr->pclass][CLA_BTH] * p_ptr->lev);
  637.     xbthb = p_ptr->bthb + p_ptr->ptohit * BTH_PLUS_ADJ
  638.         + (class_level_adj[p_ptr->pclass][CLA_BTHB] * p_ptr->lev);
  639.     /* this results in a range from 0 to 29 */
  640.     xfos = 40 - p_ptr->fos;
  641.     if (xfos < 0)
  642.         xfos = 0;
  643.     xsrh = p_ptr->srh;
  644.     /* this results in a range from 0 to 9 */
  645.     xstl = p_ptr->stl + 1;
  646.     xdis = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
  647.         + (class_level_adj[p_ptr->pclass][CLA_DISARM] * p_ptr->lev / 3);
  648.     xsave = p_ptr->save + stat_adj(A_WIS)
  649.         + (class_level_adj[p_ptr->pclass][CLA_SAVE] * p_ptr->lev / 3);
  650.     xdev = p_ptr->save + stat_adj(A_INT)
  651.         + (class_level_adj[p_ptr->pclass][CLA_DEVICE] * p_ptr->lev / 3);
  652.  
  653.     (void)sprintf(xinfra, "%d feet", py.flags.see_infra * 10);
  654.  
  655.     (void)fprintf(file1, "(Miscellaneous Abilities)\n\n");
  656.     (void)fprintf(file1, " Fighting    : %-10s", likert(xbth, 12));
  657.     (void)fprintf(file1, "   Stealth     : %-10s", likert(xstl, 1));
  658.     (void)fprintf(file1, "   Perception  : %s\n", likert(xfos, 3));
  659.     (void)fprintf(file1, " Bows/Throw  : %-10s", likert(xbthb, 12));
  660.     (void)fprintf(file1, "   Disarming   : %-10s", likert(xdis, 8));
  661.     (void)fprintf(file1, "   Searching   : %s\n", likert(xsrh, 6));
  662.     (void)fprintf(file1, " Saving Throw: %-10s", likert(xsave, 6));
  663.     (void)fprintf(file1, "   Magic Device: %-10s", likert(xdev, 6));
  664.     (void)fprintf(file1, "   Infra-Vision: %s\n\n", xinfra);
  665.     /* Write out the character's history     */
  666.     (void)fprintf(file1, "Character Background\n");
  667.     for (i = 0; i < 4; i++)
  668.         (void)fprintf(file1, " %s\n", py.misc.history[i]);
  669.     /* Write out the equipment list.         */
  670.     j = 0;
  671.     (void)fprintf(file1, "\n  [Character's Equipment List]\n\n");
  672.     if (equip_ctr == 0)
  673.         (void)fprintf(file1, "  Character has no equipment in use.\n");
  674.     else
  675.         for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) {
  676.         i_ptr = &inventory[i];
  677.         if (i_ptr->tval != TV_NOTHING) {
  678.             switch (i) {
  679.               case INVEN_WIELD:
  680.             p = "You are wielding";
  681.             break;
  682.               case INVEN_HEAD:
  683.             p = "Worn on head";
  684.             break;
  685.               case INVEN_NECK:
  686.             p = "Worn around neck";
  687.             break;
  688.               case INVEN_BODY:
  689.             p = "Worn on body";
  690.             break;
  691.               case INVEN_ARM:
  692.             p = "Worn on shield arm";
  693.             break;
  694.               case INVEN_HANDS:
  695.             p = "Worn on hands";
  696.             break;
  697.               case INVEN_RIGHT:
  698.             p = "Right ring finger";
  699.             break;
  700.               case INVEN_LEFT:
  701.             p = "Left  ring finger";
  702.             break;
  703.               case INVEN_FEET:
  704.             p = "Worn on feet";
  705.             break;
  706.               case INVEN_OUTER:
  707.             p = "Worn about body";
  708.             break;
  709.               case INVEN_LIGHT:
  710.             p = "Light source is";
  711.             break;
  712.               case INVEN_AUX:
  713.             p = "Secondary weapon";
  714.             break;
  715.               default:
  716.             p = "*Unknown value*";
  717.             break;
  718.             }
  719.             objdes(prt2, &inventory[i], TRUE);
  720.             (void)fprintf(file1, "  %c) %-19s: %s\n", j + 'a', p, prt2);
  721.             j++;
  722.         }
  723.         }
  724.  
  725.     /* Write out the character's inventory.         */
  726.     (void)fprintf(file1, "%c\n\n", CTRL('L'));
  727.     (void)fprintf(file1, "  [General Inventory List]\n\n");
  728.     if (inven_ctr == 0)
  729.         (void)fprintf(file1, "  Character has no objects in inventory.\n");
  730.     else {
  731.         for (i = 0; i < inven_ctr; i++) {
  732.         objdes(prt2, &inventory[i], TRUE);
  733.         (void)fprintf(file1, "%c) %s\n", i + 'a', prt2);
  734.         }
  735.     }
  736.     (void)fprintf(file1, "%c", CTRL('L'));
  737.  
  738.     fprintf(file1, "  [%s%s Home Inventory]\n\n", py.misc.name,
  739.         (toupper(py.misc.name[strlen(py.misc.name)-1]) == 'S' ? "'" : "'s"));
  740.     if (store[MAX_STORES-1].store_ctr == 0)
  741.         (void) fprintf(file1, "  Character has no objects at home.\n");
  742.     else {
  743.         for (i = 0; i < store[MAX_STORES-1].store_ctr; i++) {
  744.         if (i==12) fprintf(file1, "\n");  
  745.         objdes(prt2, &store[MAX_STORES-1].store_inven[i].sitem, TRUE);
  746.         (void) fprintf(file1, "%c) %s\n", (i%12)+'a', prt2);
  747.         }
  748.     }
  749.     (void) fprintf(file1, "%c", CTRL('L'));
  750.     
  751.     (void)fclose(file1);
  752.     prt("Completed.", 0, 0);
  753.     return TRUE;
  754.     } else {
  755.     if (fd >= 0)
  756.         (void)close(fd);
  757.     (void)sprintf(out_val, "Can't open file %s:", filename1);
  758.     msg_print(out_val);
  759.     return FALSE;
  760.     }
  761. }
  762.